/*
 * KeyEvent.java  0.4.0 / Oct 24, 2010
 *
 * Copyright (c) 2010 - 2011, cute4j.com and contributors.
 *
 * This software is licensed under the LGPL version 2.1 license.
 * A copy of this license is included in the file LICENSE-LGPL.txt.
 */
package com.cute4j.swing.events;

import com.cute4j.swing.Component;

/**
 * Key Event.
 *
 * @cute4j.native
 *    generate="header"
 *
 * @author Slobodan Vrkacevic
 * @version 0.4.0
 */
public class KeyEvent extends InputEvent {

// Public Static Fields. -------------------------------------------------------

  /**
   * Key typed id.
   */
  public static final int KEY_TYPED = 400;

  /**
   * Key pressed id.
   */
  public static final int KEY_PRESSED = 401;

  /**
   * Key release id.
   */
  public static final int KEY_RELEASED = 402;

  /* Virtual key codes. */

// CS:OFF

  public static final int VK_ENTER = '\n';
  public static final int VK_BACK_SPACE = '\b';
  public static final int VK_TAB = '\t';
  public static final int VK_CANCEL = 0x03;
  public static final int VK_CLEAR = 0x0C;
  public static final int VK_SHIFT = 0x10;
  public static final int VK_CONTROL = 0x11;
  public static final int VK_ALT = 0x12;
  public static final int VK_PAUSE = 0x13;
  public static final int VK_CAPS_LOCK = 0x14;
  public static final int VK_ESCAPE = 0x1B;
  public static final int VK_SPACE = 0x20;
  public static final int VK_PAGE_UP = 0x21;
  public static final int VK_PAGE_DOWN = 0x22;
  public static final int VK_END = 0x23;
  public static final int VK_HOME = 0x24;
  public static final int VK_LEFT = 0x25;
  public static final int VK_UP = 0x26;
  public static final int VK_RIGHT = 0x27;
  public static final int VK_DOWN = 0x28;
  public static final int VK_COMMA = 0x2C;
  public static final int VK_MINUS = 0x2D;
  public static final int VK_PERIOD = 0x2E;
  public static final int VK_SLASH  = 0x2F;
  public static final int VK_0 = 0x30;
  public static final int VK_1 = 0x31;
  public static final int VK_2 = 0x32;
  public static final int VK_3 = 0x33;
  public static final int VK_4 = 0x34;
  public static final int VK_5 = 0x35;
  public static final int VK_6 = 0x36;
  public static final int VK_7 = 0x37;
  public static final int VK_8 = 0x38;
  public static final int VK_9 = 0x39;
  public static final int VK_SEMICOLON = 0x3B;
  public static final int VK_EQUALS = 0x3D;
  public static final int VK_A = 0x41;
  public static final int VK_B = 0x42;
  public static final int VK_C = 0x43;
  public static final int VK_D = 0x44;
  public static final int VK_E = 0x45;
  public static final int VK_F = 0x46;
  public static final int VK_G = 0x47;
  public static final int VK_H = 0x48;
  public static final int VK_I = 0x49;
  public static final int VK_J = 0x4A;
  public static final int VK_K = 0x4B;
  public static final int VK_L = 0x4C;
  public static final int VK_M = 0x4D;
  public static final int VK_N = 0x4E;
  public static final int VK_O = 0x4F;
  public static final int VK_P = 0x50;
  public static final int VK_Q = 0x51;
  public static final int VK_R = 0x52;
  public static final int VK_S = 0x53;
  public static final int VK_T = 0x54;
  public static final int VK_U = 0x55;
  public static final int VK_V = 0x56;
  public static final int VK_W = 0x57;
  public static final int VK_X = 0x58;
  public static final int VK_Y = 0x59;
  public static final int VK_Z = 0x5A;
  public static final int VK_OPEN_BRACKET = 0x5B;
  public static final int VK_BACK_SLASH = 0x5C;
  public static final int VK_CLOSE_BRACKET = 0x5D;
  public static final int VK_NUMPAD0 = 0x60;
  public static final int VK_NUMPAD1 = 0x61;
  public static final int VK_NUMPAD2 = 0x62;
  public static final int VK_NUMPAD3 = 0x63;
  public static final int VK_NUMPAD4 = 0x64;
  public static final int VK_NUMPAD5 = 0x65;
  public static final int VK_NUMPAD6 = 0x66;
  public static final int VK_NUMPAD7 = 0x67;
  public static final int VK_NUMPAD8 = 0x68;
  public static final int VK_NUMPAD9 = 0x69;
  public static final int VK_MULTIPLY = 0x6A;
  public static final int VK_ADD = 0x6B;
  public static final int VK_SEPARATER = 0x6C;
  public static final int VK_SEPARATOR = 0x6C;
  public static final int VK_SUBTRACT = 0x6D;
  public static final int VK_DECIMAL = 0x6E;
  public static final int VK_DIVIDE = 0x6F;
  public static final int VK_DELETE = 0x7F;
  public static final int VK_NUM_LOCK = 0x90;
  public static final int VK_SCROLL_LOCK = 0x91;
  public static final int VK_F1 = 0x70;
  public static final int VK_F2 = 0x71;
  public static final int VK_F3 = 0x72;
  public static final int VK_F4 = 0x73;
  public static final int VK_F5 = 0x74;
  public static final int VK_F6 = 0x75;
  public static final int VK_F7 = 0x76;
  public static final int VK_F8 = 0x77;
  public static final int VK_F9 = 0x78;
  public static final int VK_F10 = 0x79;
  public static final int VK_F11 = 0x7A;
  public static final int VK_F12 = 0x7B;
  public static final int VK_F13 = 0xF000;
  public static final int VK_F14 = 0xF001;
  public static final int VK_F15 = 0xF002;
  public static final int VK_F16 = 0xF003;
  public static final int VK_F17 = 0xF004;
  public static final int VK_F18 = 0xF005;
  public static final int VK_F19 = 0xF006;
  public static final int VK_F20 = 0xF007;
  public static final int VK_F21 = 0xF008;
  public static final int VK_F22 = 0xF009;
  public static final int VK_F23 = 0xF00A;
  public static final int VK_F24 = 0xF00B;
  public static final int VK_PRINTSCREEN = 0x9A;
  public static final int VK_INSERT = 0x9B;
  public static final int VK_HELP = 0x9C;
  public static final int VK_META = 0x9D;
  public static final int VK_BACK_QUOTE = 0xC0;
  public static final int VK_QUOTE = 0xDE;
  public static final int VK_KP_UP = 0xE0;
  public static final int VK_KP_DOWN = 0xE1;
  public static final int VK_KP_LEFT = 0xE2;
  public static final int VK_KP_RIGHT = 0xE3;
  public static final int VK_AMPERSAND = 0x96;
  public static final int VK_ASTERISK = 0x97;
  public static final int VK_QUOTEDBL = 0x98;
  public static final int VK_LESS = 0x99;
  public static final int VK_GREATER = 0xa0;
  public static final int VK_BRACELEFT = 0xa1;
  public static final int VK_BRACERIGHT = 0xa2;
  public static final int VK_AT = 0x0200;
  public static final int VK_COLON = 0x0201;
  public static final int VK_CIRCUMFLEX = 0x0202;
  public static final int VK_DOLLAR = 0x0203;
  public static final int VK_EURO_SIGN = 0x0204;
  public static final int VK_EXCLAMATION_MARK = 0x0205;
  public static final int VK_INVERTED_EXCLAMATION_MARK = 0x0206;
  public static final int VK_LEFT_PARENTHESIS = 0x0207;
  public static final int VK_NUMBER_SIGN = 0x0208;
  public static final int VK_PLUS = 0x0209;
  public static final int VK_RIGHT_PARENTHESIS = 0x020A;
  public static final int VK_UNDERSCORE = 0x020B;
  public static final int VK_FINAL = 0x0018;
  public static final int VK_ALPHANUMERIC = 0x00F0;
  public static final int VK_CODE_INPUT = 0x0102;
  public static final int VK_INPUT_METHOD_ON_OFF = 0x0107;
  public static final int VK_CUT  = 0xFFD1;
  public static final int VK_COPY = 0xFFCD;
  public static final int VK_PASTE = 0xFFCF;
  public static final int VK_UNDO = 0xFFCB;
  public static final int VK_AGAIN = 0xFFC9;
  public static final int VK_FIND = 0xFFD0;
  public static final int VK_PROPS = 0xFFCA;
  public static final int VK_STOP = 0xFFC8;
  public static final int VK_COMPOSE = 0xFF20;
  public static final int VK_ALT_GRAPH = 0xFF7E;
  public static final int VK_UNDEFINED = 0x0;
  public static final char CHAR_UNDEFINED = 0xFFFF;

// CS:ON

// Private Static Fields. ------------------------------------------------------

  private static final long serialVersionUID = -5748151708835518863L;

// Private Fields. -------------------------------------------------------------

  private int keyCode;
  private char keyChar;

// Public Constructors. --------------------------------------------------------

  /**
   * Constructs new KeyEvent object.
   *
   * @param source the event source
   * @param id the event id
   * @param when the time the event occurred
   * @param modifiers the modifiers
   * @param keyCode the key code
   * @param keyChar the key char
   *
   * @throws IllegalArgumentException if the source is <tt>null</tt>
   */
  public KeyEvent(Component source, int id, long when, int modifiers,
                  int keyCode, char keyChar) {
    super(source, id, when, modifiers);
    this.keyCode = keyCode;
    this.keyChar = keyChar;
  }

  /**
   * Constructs new KeyEvent object.
   *
   * @param source the event source
   * @param id the event id
   * @param modifiers the modifiers
   * @param keyCode the key code
   * @param keyChar the key char
   *
   * @throws IllegalArgumentException if the source is <tt>null</tt>
   */
  public KeyEvent(Component source, int id, int modifiers, int keyCode,
                  char keyChar) {
    this(source, id, 0, modifiers, keyCode, keyChar);
  }

// Public Methods. -------------------------------------------------------------

  /**
   * Returns key code.
   *
   * @return key code
   */
  public int getKeyCode() {
    return keyCode;
  }

  /**
   * Returns key char.
   *
   * @return key char
   */
  public char getKeyChar() {
    return keyChar;
  }

  /**
   * Returns the text name of key code.
   *
   * @param keyCode the key code
   *
   * @return the text name of the key code
   */
  public static String getKeyText(int keyCode) { // NOPMD
    switch (keyCode) { // NOPMD
      case VK_CANCEL:
        return "Cancel";
      case VK_BACK_SPACE:
        return "Backspace";
      case VK_TAB:
        return "Tab";
      case VK_ENTER:
        return "Enter";
      case VK_CLEAR:
        return "Clear";
      case VK_SHIFT:
        return "Shift";
      case VK_CONTROL:
        return "Ctrl";
      case VK_ALT:
        return "Alt";
      case VK_PAUSE:
        return "Pause";
      case VK_CAPS_LOCK:
        return "Caps Lock";
      case VK_FINAL:
        return "Final";
      case VK_ESCAPE:
        return "Escape";
      case VK_SPACE:
        return "Space";
      case VK_PAGE_UP:
        return "Page Up";
      case VK_PAGE_DOWN:
        return "Page Down";
      case VK_END:
        return "End";
      case VK_HOME:
        return "Home";
      case VK_LEFT:
        // falls through
      case VK_KP_LEFT:
        return "Left";
      case VK_UP:
        // falls through
      case VK_KP_UP:
        return "Up";
      case VK_RIGHT:
        // falls through
      case VK_KP_RIGHT:
        return "Right";
      case VK_DOWN:
        // falls through
      case VK_KP_DOWN:
        return "Down";
      case VK_MINUS:
        return "Minus";
      case VK_MULTIPLY:
        return "NumPad *";
      case VK_ADD:
        return "NumPad +";
      case VK_SEPARATOR:
        return "NumPad ,";
      case VK_SUBTRACT:
        return "NumPad -";
      case VK_DECIMAL:
        return "NumPad .";
      case VK_DIVIDE:
        return "NumPad /";
      case VK_DELETE:
        return "Delete";
      case VK_NUM_LOCK:
        return "Num Lock";
      case VK_SCROLL_LOCK:
        return "Scroll Lock";
      case VK_AMPERSAND:
        return "Ampersand";
      case VK_ASTERISK:
        return "Asterisk";
      case VK_QUOTEDBL:
        return "Double Quote";
      case VK_LESS:
        return "Less";
      case VK_PRINTSCREEN:
        return "Print Screen";
      case VK_INSERT:
        return "Insert";
      case VK_HELP:
        return "Help";
      case VK_META:
        return "Meta";
      case VK_GREATER:
        return "Greater";
      case VK_BRACELEFT:
        return "Left Brace";
      case VK_BRACERIGHT:
        return "Right Brace";
      case VK_BACK_QUOTE:
        return "Back Quote";
      case VK_QUOTE:
        return "Quote";
      case VK_ALPHANUMERIC:
        return "Alphanumeric";
      case VK_INPUT_METHOD_ON_OFF:
        return "Input Method On/Off";
      case VK_AT:
        return "At";
      case VK_COLON:
        return "Colon";
      case VK_CIRCUMFLEX:
        return "Circumflex";
      case VK_DOLLAR:
        return "Dollar";
      case VK_EURO_SIGN:
        return "Euro";
      case VK_EXCLAMATION_MARK:
        return "Exclamation Mark";
      case VK_INVERTED_EXCLAMATION_MARK:
        return "Inverted Exclamation Mark";
      case VK_LEFT_PARENTHESIS:
        return "Left Parenthesis";
      case VK_NUMBER_SIGN:
        return "Number Sign";
      case VK_PLUS:
        return "Plus";
      case VK_RIGHT_PARENTHESIS:
        return "Right Parenthesis";
      case VK_UNDERSCORE:
        return "Underscore";
      case VK_COMPOSE:
        return "Compose";
      case VK_ALT_GRAPH:
        return "Alt Graph";
      case VK_STOP:
        return "Stop";
      case VK_AGAIN:
        return "Again";
      case VK_PROPS:
        return "Props";
      case VK_UNDO:
        return "Undo";
      case VK_COPY:
        return "Copy";
      case VK_PASTE:
        return "Paste";
      case VK_FIND:
        return "Find";
      case VK_CUT:
        return "Cut";
      case VK_COMMA:
        // falls through
      case VK_PERIOD:
        // falls through
      case VK_SLASH:
        // falls through
      case VK_0:
        // falls through
      case VK_1:
        // falls through
      case VK_2:
        // falls through
      case VK_3:
        // falls through
      case VK_4:
        // falls through
      case VK_5:
        // falls through
      case VK_6:
        // falls through
      case VK_7:
        // falls through
      case VK_8:
        // falls through
      case VK_9:
        // falls through
      case VK_SEMICOLON:
        // falls through
      case VK_EQUALS:
        // falls through
      case VK_A:
        // falls through
      case VK_B:
        // falls through
      case VK_C:
        // falls through
      case VK_D:
        // falls through
      case VK_E:
        // falls through
      case VK_F:
        // falls through
      case VK_G:
        // falls through
      case VK_H:
        // falls through
      case VK_I:
        // falls through
      case VK_J:
        // falls through
      case VK_K:
        // falls through
      case VK_L:
        // falls through
      case VK_M:
        // falls through
      case VK_N:
        // falls through
      case VK_O:
        // falls through
      case VK_P:
        // falls through
      case VK_Q:
        // falls through
      case VK_R:
        // falls through
      case VK_S:
        // falls through
      case VK_T:
        // falls through
      case VK_U:
        // falls through
      case VK_V:
        // falls through
      case VK_W:
        // falls through
      case VK_X:
        // falls through
      case VK_Y:
        // falls through
      case VK_Z:
        // falls through
      case VK_OPEN_BRACKET:
        // falls through
      case VK_BACK_SLASH:
        // falls through
      case VK_CLOSE_BRACKET:
        return String.valueOf((char)keyCode);
      case VK_NUMPAD0:
        // falls through
      case VK_NUMPAD1:
        // falls through
      case VK_NUMPAD2:
        // falls through
      case VK_NUMPAD3:
        // falls through
      case VK_NUMPAD4:
        // falls through
      case VK_NUMPAD5:
        // falls through
      case VK_NUMPAD6:
        // falls through
      case VK_NUMPAD7:
        // falls through
      case VK_NUMPAD8:
        // falls through
      case VK_NUMPAD9:
        return "NumPad-" + (keyCode - VK_NUMPAD0);
      case VK_F1:
        // falls through
      case VK_F2:
        // falls through
      case VK_F3:
        // falls through
      case VK_F4:
        // falls through
      case VK_F5:
        // falls through
      case VK_F6:
        // falls through
      case VK_F7:
        // falls through
      case VK_F8:
        // falls through
      case VK_F9:
        // falls through
      case VK_F10:
        // falls through
      case VK_F11:
        // falls through
      case VK_F12:
        return "F" + (keyCode - (VK_F1 - 1));
      case VK_F13:
        // falls through
      case VK_F14:
        // falls through
      case VK_F15:
        // falls through
      case VK_F16:
        // falls through
      case VK_F17:
        // falls through
      case VK_F18:
        // falls through
      case VK_F19:
        // falls through
      case VK_F20:
        // falls through
      case VK_F21:
        // falls through
      case VK_F22:
        // falls through
      case VK_F23:
        // falls through
      case VK_F24:
        return "F" + (keyCode - (VK_F13 - 13));
      default:
        return "Unknown keyCode: 0x" + Integer.toString(keyCode, 16);
    }
  }

  /**
   * Returns <tt>true</tt> if the key is action key.
   *
   * @return <tt>true</tt> if the key is action key
   */
  public boolean isActionKey() {
    switch (keyCode) { // NOPMD
      case VK_PAUSE:
        // falls through
      case VK_CAPS_LOCK:
        // falls through
      case VK_FINAL:
        // falls through
      case VK_PAGE_UP:
        // falls through
      case VK_PAGE_DOWN:
        // falls through
      case VK_END:
        // falls through
      case VK_HOME:
        // falls through
      case VK_LEFT:
        // falls through
      case VK_UP:
        // falls through
      case VK_RIGHT:
        // falls through
      case VK_DOWN:
        // falls through
      case VK_F1:
        // falls through
      case VK_F2:
        // falls through
      case VK_F3:
        // falls through
      case VK_F4:
        // falls through
      case VK_F5:
        // falls through
      case VK_F6:
        // falls through
      case VK_F7:
        // falls through
      case VK_F8:
        // falls through
      case VK_F9:
        // falls through
      case VK_F10:
        // falls through
      case VK_F11:
        // falls through
      case VK_F12:
        // falls through
      case VK_NUM_LOCK:
        // falls through
      case VK_SCROLL_LOCK:
        // falls through
      case VK_PRINTSCREEN:
        // falls through
      case VK_INSERT:
        // falls through
      case VK_HELP:
        // falls through
      case VK_KP_UP:
        // falls through
      case VK_KP_DOWN:
        // falls through
      case VK_KP_LEFT:
        // falls through
      case VK_KP_RIGHT:
        // falls through
      case VK_ALPHANUMERIC:
        // falls through
      case VK_INPUT_METHOD_ON_OFF:
        // falls through
      case VK_F13:
        // falls through
      case VK_F14:
        // falls through
      case VK_F15:
        // falls through
      case VK_F16:
        // falls through
      case VK_F17:
        // falls through
      case VK_F18:
        // falls through
      case VK_F19:
        // falls through
      case VK_F20:
        // falls through
      case VK_F21:
        // falls through
      case VK_F22:
        // falls through
      case VK_F23:
        // falls through
      case VK_F24:
        // falls through
      case VK_STOP:
        // falls through
      case VK_AGAIN:
        // falls through
      case VK_PROPS:
        // falls through
      case VK_UNDO:
        // falls through
      case VK_COPY:
        // falls through
      case VK_PASTE:
        // falls through
      case VK_FIND:
        // falls through
      case VK_CUT:
        return true;
    }
    return false;
  }

// Overridden Methods. ---------------------------------------------------------

  /**
   * {@inheritDoc}
   */
  public String paramString() {
    StringBuffer sb = new StringBuffer(90);
    switch (id) {
      case KEY_PRESSED:
        sb.append("KEY_PRESSED");
        break;
      case KEY_RELEASED:
        sb.append("KEY_RELEASED");
        break;
      case KEY_TYPED:
        sb.append("KEY_TYPED");
        break;
      default:
        sb.append("unknown type");
    }
    sb.append(",keyCode=");
    sb.append(getKeyCode());
    sb.append(",keyText=");
    sb.append(getKeyText(keyCode));
    sb.append(",keyChar=");
    if (isActionKey() || (keyCode == VK_SHIFT) || (keyCode == VK_CONTROL) ||
        (keyCode == VK_ALT)) {
      sb.append("Undefined keyChar");
    } else {
      if ((keyChar == VK_BACK_SPACE) || (keyChar == VK_TAB) ||
          (keyChar == VK_ENTER) || (keyChar == VK_ESCAPE) ||
          (keyChar == VK_DELETE)) {
        sb.append(getKeyText(keyChar));
      } else {
        sb.append('\'');
        sb.append(getKeyChar());
        sb.append('\'');
      }
    }
    return sb.toString();
  }

}
